package cn.mw.cmdb.virtualization.strategy.handler.query;

import cn.mw.cmdb.virtualization.constant.MwVirtualizationConstant;
import cn.mw.cmdb.virtualization.dto.*;
import cn.mw.cmdb.virtualization.param.VirtualizationParam;
import cn.mw.cmdb.virtualization.strategy.handler.HostDtoHandler;
import cn.mw.cmdb.virtualization.strategy.handler.VMDtoHandler;
import cn.mw.cmdb.virtualization.strategy.handler.VirtualizationTypeHandler;
import cn.mw.main.api.common.ZabbixDubboService;
import cn.mw.microMonitorCommon.constants.ZabbixApiConstants;
import cn.mw.microMonitorCommon.entity.zabbix.MWZabbixAPIResult;
import cn.mw.microMonitorCommon.enums.UnicloudTypeEnum;
import cn.mw.microMonitorCommon.enums.VcenterTypeEnum;
import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.Lists;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @description 虚拟化、数据中心、主机池、集群数据
 */
@Service
@Slf4j
public class VirtualizationBasicTypeHandler implements VirtualizationTypeHandler {

    @DubboReference(check = false, timeout = 120000)
    private ZabbixDubboService zabbixDubboService;

    @Override
    public List<String> getType() {
        return Arrays.asList(VcenterTypeEnum.DATACNETER.getType(), VcenterTypeEnum.CLUSTER.getType(), UnicloudTypeEnum.HOST_POOL.getType(), UnicloudTypeEnum.CLUSTER.getType());
    }

    @Override
    public Object getTypeData(List<VirtualizationBaseDto> baseDtos, VirtualizationParam param, Integer serverId) {
        VirtualizationDto virtualizationDto = new VirtualizationDto();
        try {
            //获取hostID集合
            List<String> hostIds = baseDtos.stream().filter(item -> StringUtils.isNotEmpty(item.getHostId())).map(s -> s.getHostId()).collect(Collectors.toList());
            //查询主机需要的数据
            List<String> itemNames = getItemNames(param.getQueryType());
            //查询zabbix数据
            List<ItemLatestConvertDto> latestConvertDtos = new ArrayList<>();
            List<List<String>> partition = Lists.partition(hostIds, 100);
            for (List<String> ids : partition) {
                MWZabbixAPIResult result = zabbixDubboService.getZabbixApiResult(ZabbixApiConstants.ITEM_GET_BY_SEARCH, serverId, itemNames, ids);
                if(result == null || result.isFail()){return virtualizationDto;}
                latestConvertDtos.addAll(JSONArray.parseArray(String.valueOf(result.getData()), ItemLatestConvertDto.class));
            }
            log.info("VirtualizationBasicTypeHandler{} getTypeData() latestConvertDtos>>>"+latestConvertDtos.size());
            Map<String, List<ItemLatestConvertDto>> hostItemMap = latestConvertDtos.stream().collect(Collectors.groupingBy(item -> item.getHostid()));
            Map<String, VirtualizationBaseDto> baseDtoMap = baseDtos.stream().collect(Collectors.toMap(s -> s.getHostId(), s -> s));
            List realDatas = new ArrayList();
            for (String hostId : hostItemMap.keySet()) {
                List<ItemLatestConvertDto> dtos = hostItemMap.get(hostId);
                VirtualizationBaseDto virtualizationBaseDto = baseDtoMap.get(hostId);
                switch (param.getQueryType()){
                    case HOST:
                        VirtualizationHostDto hostDto = new VirtualizationHostDto();
                        BeanUtils.copyProperties(virtualizationBaseDto,hostDto);
                        setFieldInfo(hostDto.getClass(),dtos);
                        realDatas.add(hostDto);
                        break;
                    case VM:
                        VirtualizationVMDto vmDto = new VirtualizationVMDto();
                        BeanUtils.copyProperties(virtualizationBaseDto,vmDto);
                        setFieldInfo(vmDto.getClass(),dtos);
                        realDatas.add(vmDto);
                }
            }
            virtualizationDto = handlerData(realDatas, param.getQueryType());
        }catch (Throwable e){
            log.error("VirtualizationBasicTypeHandler{} getTypeData() error",e);
        }
        return virtualizationDto;
    }


    private VirtualizationDto handlerData(List realDatas,String queryType){
        VirtualizationDto virtualizationDto = new VirtualizationDto();
        switch (queryType){
            case HOST:
                HostDtoHandler handler = new HostDtoHandler();
                virtualizationDto = handler.handler(realDatas);
                break;
            case VM:
                VMDtoHandler vmDtoHandler = new VMDtoHandler();
                virtualizationDto = vmDtoHandler.handler(realDatas);
        }
        return virtualizationDto;
    }


    private List<String> getItemNames(String queryType){
        switch (queryType){
            case HOST:
                return MwVirtualizationConstant.HOST_ITEMS;
            case VM:
                return MwVirtualizationConstant.VM_ITEMS;
        }
        return null;
    }

    private void setFieldInfo(Class cls,List<ItemLatestConvertDto> convertDtos) throws IllegalAccessException {
        for (ItemLatestConvertDto convertDto : convertDtos) {
            String name = convertDto.getName();
            if(name.contains("[")){
                name = name.split("]")[1];
            }
            Field[] fields = cls.getDeclaredFields();
            for (Field field : fields) {
                if(!field.isAnnotationPresent(Schema.class)){continue;}
                Schema schema = field.getAnnotation(Schema.class);
                if(!schema.description().equals(name)){continue;}
                field.setAccessible(true);
                Object value = field.get(cls);
                String lastvalue = convertDto.getLastvalue();
                Boolean numeric = isNumeric(lastvalue);
                if(!numeric){
                    field.set(cls,lastvalue);
                    continue;
                }
                if(value != null){
                    String strValue = value.toString().split("_")[0];
                    field.set(cls, new BigDecimal(lastvalue).add(new BigDecimal(strValue)).toString()+"_"+convertDto.getUnits());
                }else{
                    field.set(cls,lastvalue+"_"+convertDto.getUnits());
                }
            }
        }
    }

    public Boolean isNumeric(String value) {
        // 定义数字的正则表达式，允许负号和小数点
        String numericRegex = "^[-+]?[0-9]*\\.?[0-9]+$";
        // 创建 Pattern 对象
        Pattern pattern = Pattern.compile(numericRegex);
        // 创建 Matcher 对象
        Matcher matcher = pattern.matcher(value);
        // 判断是否匹配
        if(!matcher.matches()){
            return false;
        }
        return true;
    }
}
